#include <stdio.h>
#include <windows.h>
#include "luthor.h"
using namespace LuaWanbHash;
using namespace std;

#define OP LT::op()
#define CL cl()
//Var LT::STbl::Tnode::nil=ltMV(NotFound());

static Tbl et=OP.CL;
void stdtst(string re, string dta) {
  Tbl res=Luthor(re).find(dta),t;
  cout << re <<" + "<<dta<<" = ";
  for (int i=0;i<res->len();i++) {
     t=res->get(i,et);
     cout <<"("<<t->get("matchstart")<<") "<<t->get("match")<<((i==res->len()-1)?"":" -- ");
  }
  cout <<"\n";
}

int main() {
   Tbl t=OP.i("doe","deer").i("ray","sun").i("me","myself").CL;
   Var k,v;
   ltForEach(k,v,t) cout <<k<<":"<<v<<"\n";
   Tbl keys=t->keys();
   ltForEachL(v,keys) cout <<v<<"\n";
   Tbl tom=Luthor("tom.*?river").find("a guy named tom lives in a van by the river");
   cout << tom<<"\n";
   int st,nd;
   Luthor t1("<@tag(\\w+?)[^\\w].*?/@tag@>");
   st=GetTickCount();
   Tbl res;
   for (int i=0;i<20;i++) {
     res=t1.find("<input> hi </input> some <looks> like a tag but </not> stuff outside <sarcasm> yeah right </sarcasm>");
   }
   nd=GetTickCount();
   cout << "delt="<<nd-st<<"\n";
   for (int i=0;i<res->len();i++)
      cout <<i<<" : "<<res->get(i,et)->get("match")<<"\n";
   Luthor parser=Luthor().add("@1(\\d+)",OP.i("type","i").CL)
                         .add("@1(\\d+\\.\\d+",OP.i("type","f").CL)
                         .add("\"@1((\\.|[^\"])*)\"",OP.i("type","s").CL)
                         .add("@1([\\w/]+)$",OP.i("type","last").CL);
   res=parser.find("12 13.7\"twelve + 74\" 3.14 22/7");
   cout<<res<<"\n";
   for (int i=0;i<res->len();i++)
     cout <<"var ="<<res->get(i,et)->get("1")<<" type ="<<res->get(i,et)->get("type")<<"\n";
   stdtst("abracadabra$","abracadabracadabra");
   stdtst("a...b","abababbb");
   stdtst("XXXXXX","..XXXXXX");
   stdtst("\\)","()");
   stdtst("a]","a]a");
   stdtst("}","}");
   stdtst("\\}","}");
   stdtst("\\]","]");
   stdtst("]","]");
   stdtst("}","}");
   stdtst("{","{");
   stdtst("^a","ax");
   stdtst("\\^a","a^a");
   stdtst("a\\^","a^");
   stdtst("a$","aa");
   stdtst("a\\$","a$");
   stdtst("^$","");
   stdtst("a($)","aa");
   stdtst("a*(^a)","aa");
   stdtst("(..)*(...)*","a");
   stdtst("(..)*(...)*","abcd");
   stdtst("(ab|a)(bc|c)","abc");
   // stdtst("(ab)c|abc","abc"); // these don't make sense to me
   stdtst("((a|a)|a)","a");
   stdtst("(a*)(a|aa)","aaaa");
   stdtst("a*(a.|aa)","aaaa");
   stdtst("(ab|cd|aef)","aef");
   stdtst("(a|b)?.*","b");  // top blows up
   stdtst("((a|b)c|a(b|c))","ac");
   stdtst("((a|b)c|a(b|c))","ab");
   stdtst("((a|b)*c|(a|ab)*c)","abc");
   stdtst("((a|b)*c|(a|ab)*c)","xc");
   stdtst("((.a|.b).*|.*(.a|.b))","xa");
   stdtst("a?(ab|ba)ab","abab");
   stdtst("(ab|abab)","abbabab");
   stdtst("(aba|bab|bba)","baaabbbaba");
   stdtst("(aba|bab)","baaabbbaba");
   stdtst("((aa|aaa)*|(a|aaaaa))","aa"); // blows up
   stdtst("((a.|.a.)*|(a|.a...))","aa"); // blows up
   stdtst("(ab|a)","xabc");
   stdtst("(ab|a)","xxabc");
   stdtst("<tr>.*</tr>","<tr>couple</tr><tr>of rows</tr><tr>to</tr><tr>check</tr><tr>greedy</tr>");
   stdtst("<tr>.*?</tr>","<tr>couple</tr><tr>of rows</tr><tr>to</tr><tr>check</tr><tr>greedy</tr>");
   cout << Luthor("<@tt(tr|td).*?/@tt@>").find("<tr bgcolor=\"#EEEEEE\"><td height=\"30\" class=\"ygtb\"><b>United States Steel Corp. (X)</b></td><td align=\"right\" valign=\"bottom\" nowrap><small>On <span id=\"yfs_t10_x\">May 28</span>: </small><big><b><span id=\"yfs_l10_x\">32.80</span></b></big>&nbsp;&nbsp;<span id=\"yfs_c10_x\"> <b style=\"color:#000000;\">0.00</b></span> <span id=\"yfs_p20_x\"><b style=\"color:#000000;\"> (0.00%)</b></span>&nbsp;&nbsp;</td></tr>")<<"\n";
   return 0;
}
